﻿using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using TeacherLeftHand.DataAccess;
using TeacherLeftHand.Messages;
using TeacherLeftHand.Model;
using TeacherLeftHand.Util;

namespace TeacherLeftHand.ViewModel
{
    public class KnowledgeItemViewModel : ViewModelBase, IDataErrorInfo
    {
        #region Constructor
        public KnowledgeItemViewModel()
        {
            SubjectList = _kiAccessor.GetSubjectList();
            TopicList = _kiAccessor.GetTopicList();

            //register message
            Messenger.Default.Register<KnowledgeItem>(this, "SelectedKnowledgeItem", selectedKI =>
                                                                                         {
                                                                                             _isCreateNew = false;
                                                                                             if (selectedKI != null)
                                                                                             {
                                                                                                 IsEditable = false;
                                                                                                 IsEditButtonEnable =
                                                                                                     true;
                                                                                                 _ki = selectedKI;
                                                                                                 _originalKI =
                                                                                                     new KnowledgeItem(
                                                                                                         _ki);

                                                                                             }
                                                                                             else
                                                                                             {
                                                                                                 _ki = new KnowledgeItem();
                                                                                             }
                                                                                             RaisePropertyChanged("ClassLevel");
                                                                                             RaisePropertyChanged("Subject");
                                                                                             //RaisePropertyChanged("Difficulty");
                                                                                             RaisePropertyChanged("Topic");
                                                                                             RaisePropertyChanged("TopicNo");
                                                                                             RaisePropertyChanged("KIType");
                                                                                             RaisePropertyChanged("Content");
                                                                                         });

            // register create message
            Messenger.Default.Register<KnowledgeItemViewMessage>(this, Create);
        }



        #endregion

        #region properties
        private KnowledgeItem _ki = new KnowledgeItem();
        private readonly KnowledgeItemAccessor _kiAccessor = new KnowledgeItemAccessor();
        private ObservableCollection<string> _topicList = new ObservableCollection<string>();
        private bool _isEditButtonEnable = true;
        private bool _isCreateNew;

        private bool _isEditable;
        private KnowledgeItem _originalKI = new KnowledgeItem();

        public ObservableCollection<string> KITypeList
        {
            get { return DataHelper.KITypeList; }
        }

        public bool IsEditable
        {
            get
            {
                if (_ki == null) return false;
                return _isEditable;
            }
            set
            {
                if (_isEditable != value)
                {
                    _isEditable = value;
                    RaisePropertyChanged("IsEditable");
                }
            }
        }

        public bool IsEditButtonEnable
        {
            get
            {
                if (_ki == null) return false;
                return _isEditButtonEnable;
            }
            set
            {
                if (_isEditButtonEnable != value)
                {
                    _isEditButtonEnable = value;
                    RaisePropertyChanged("IsEditButtonEnable");
                }
            }
        }

        public int ClassLevel
        {
            get
            {
                if (_ki == null) return 0;
                return _ki.ClassLevel;
            }
            set
            {
                if (_ki.ClassLevel != value)
                {
                    _ki.ClassLevel = value;
                    RaisePropertyChanged("ClassLevel");
                    SubjectList = new ObservableCollection<string>(_kiAccessor.GetSubjectByClass(value));
                    TopicList = new ObservableCollection<string>(_kiAccessor.GetTopicByClassAndSubject(ClassLevel, Subject));
                }
            }
        }

        public string Content
        {
            get
            {
                if (_ki == null) return "";
                return _ki.Content;
            }
            set
            {
                if (_ki.Content != value)
                {
                    _ki.Content = value;
                    RaisePropertyChanged("Content");
                }
            }
        }

        public string KIType
        {
            get
            {
                if (_ki == null) return "";
                return _ki.KIType;
            }
            set
            {
                if (_ki.KIType != value)
                {
                    _ki.KIType = value;
                    RaisePropertyChanged("KIType");
                }
            }
        }

        public ObservableCollection<int> ClassLevelList
        {
            get { return DataHelper.ClassLevelList; }
        }

        public string Subject
        {
            get
            {
                if (_ki == null) return "";
                return _ki.Subject;
            }
            set
            {
                if (_ki.Subject != value)
                {
                    _ki.Subject = value;
                    RaisePropertyChanged("Subject");
                    TopicList = new ObservableCollection<string>(_kiAccessor.GetTopicByClassAndSubject(ClassLevel, value));
                }
            }
        }

        public string Topic
        {
            get
            {
                if (_ki == null) return "";
                return _ki.Topic;
            }
            set
            {
                if (_ki.Topic != value)
                {
                    _ki.Topic = value;
                    RaisePropertyChanged("Topic");
                }
            }
        }

        public int TopicNo
        {
            get
            {
                if (_ki == null) return 0;
                return _ki.TopicNo;
            }
            set
            {
                if (_ki.TopicNo != value)
                {
                    _ki.TopicNo = value;
                    RaisePropertyChanged("TopicNo");
                }
            }
        }

        private ICommand _saveCommand;
        public ICommand SaveCommand
        {
            get
            {
                if (_saveCommand == null)
                {
                    _saveCommand = new RelayCommand(() =>
                                                        {
                                                            if (_isCreateNew)
                                                            {
                                                                _ki.ID = Add(_ki);
                                                                if (_ki.ID > 0)
                                                                {
                                                                    var msg = new UpdateKIMessage
                                                                                  {
                                                                                      Action = UpdateAction.Add,
                                                                                      KnowledgeItem = _ki
                                                                                  };
                                                                    Messenger.Default.Send(msg);
                                                                    _isCreateNew = false;
                                                                    IsEditable = false;
                                                                    IsEditButtonEnable = true;
                                                                }
                                                            }
                                                            else if (Save(_ki))
                                                            {
                                                                var msg = new UpdateKIMessage
                                                                              {
                                                                                  Action = UpdateAction.Update,
                                                                                  KnowledgeItem = _ki
                                                                              };
                                                                Messenger.Default.Send(msg);
                                                                IsEditable = false;
                                                                IsEditButtonEnable = true;
                                                            }
                                                        }, () => CanSave);
                }
                return _saveCommand;
            }
        }

        private ICommand _cancelCommand;
        public ICommand CancelCommand
        {
            get
            {
                if (_cancelCommand == null)
                {
                    _cancelCommand = new RelayCommand(() =>
                    {
                        if (IsEditable)
                        {
                            IsEditable = false;
                            IsEditButtonEnable = true;
                            _ki = new KnowledgeItem(_originalKI);
                            RaisePropertyChanged("ClassLevel");
                            RaisePropertyChanged("Subject");
                            RaisePropertyChanged("Difficulty");
                            RaisePropertyChanged("Topic");
                            RaisePropertyChanged("TopicNo");
                            RaisePropertyChanged("KIType");
                            RaisePropertyChanged("Content");
                        }
                    });
                }
                return _cancelCommand;
            }

        }

        private ICommand _editCommand;
        public ICommand EditCommand
        {
            get
            {
                if (_editCommand == null)
                {
                    _editCommand = new RelayCommand(() =>
                    {
                        if (!IsEditable)
                        {
                            IsEditable = true;
                            IsEditButtonEnable = false;
                        }
                    });

                }
                return _editCommand;
            }
        }

        /// <summary>
        /// The <see cref="SubjectList" /> property's name.
        /// </summary>
        public const string SubjectListPropertyName = "SubjectList";

        private ObservableCollection<string> _subjectList = new ObservableCollection<string>();

        /// <summary>
        /// Gets the SubjectList property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public ObservableCollection<string> SubjectList
        {
            get
            {
                return _subjectList;
            }

            set
            {
                if (_subjectList == value)
                {
                    return;
                }

                var oldValue = _subjectList;
                _subjectList = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(SubjectListPropertyName);

            }
        }

        public ObservableCollection<string> TopicList
        {
            get { return _topicList; }
            set
            {
                if (_topicList != value)
                {
                    _topicList = value;
                    RaisePropertyChanged("TopicList");
                }
            }
        }

        /// <summary>
        /// The <see cref="CanSave" /> property's name.
        /// </summary>
        public const string CanSavePropertyName = "CanSave";

        private bool _canSave = false;

        /// <summary>
        /// Gets the CanSave property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public bool CanSave
        {
            get
            {
                return string.IsNullOrEmpty(Error);
            }

            set
            {
                if (_canSave == value)
                {
                    return;
                }

                _canSave = value;
                // Update bindings, no broadcast
                RaisePropertyChanged(CanSavePropertyName);
            }
        }

        public ICommand DeleteCommand { get; private set; }
        #endregion

        #region Implementation of IDataErrorInfo

        private const string ContentPropertyName = "Content";
        private const string ClassLevelPropertyName = "ClassLevel";
        private const string SubjectPropertyName = "Subject";
        private const string TopicPropertyName = "Topic";

        /// <summary>
        /// Gets the error message for the property with the given name.
        /// </summary>
        /// <returns>
        /// The error message for the property. The default is an empty string ("").
        /// </returns>
        /// <param name="columnName">The name of the property whose error message to get. </param>
        public string this[string columnName]
        {
            get
            {
                var msg = "";
                if (IsEditable)
                {
                    switch (columnName)
                    {
                        case ContentPropertyName:
                            if (_ki == null || string.IsNullOrEmpty(_ki.Content))
                                msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredContentMsg).ToString();
                            break;
                        case ClassLevelPropertyName:
                            if (_ki == null || _ki.ClassLevel <= 0)
                                msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredClassMsg).ToString();
                            break;
                        case SubjectPropertyName:
                            if (_ki == null || string.IsNullOrEmpty(_ki.Subject))
                                msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredSubjectMsg).ToString();
                            break;
                        case TopicPropertyName:
                            if (_ki == null || string.IsNullOrEmpty(_ki.Topic))
                                msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredTopicMsg).ToString();
                            break;
                        default:
                            break;
                    }
                    RaisePropertyChanged(CanSavePropertyName);
                }
                return msg;
            }
        }

        /// <summary>
        /// Gets an error message indicating what is wrong with this object.
        /// </summary>
        /// <returns>
        /// An error message indicating what is wrong with this object. The default is an empty string ("").
        /// </returns>
        public string Error
        {
            get
            {
                var msg = "";
                if (_ki == null || string.IsNullOrEmpty(Content))
                    msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredContentMsg).ToString();
                if (_ki == null || ClassLevel <= 0)
                    msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredClassMsg).ToString();
                if (_ki == null || string.IsNullOrEmpty(Subject))
                    msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredSubjectMsg).ToString();
                if (_ki == null || string.IsNullOrEmpty(Topic))
                    msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredTopicMsg).ToString();
                return msg;
            }
        }

        #endregion

        #region methods
        public void Create(KnowledgeItemViewMessage msg)
        {
            _isCreateNew = true;
            _ki = new KnowledgeItem();
            
            if (!IsEditable)
            {
                IsEditable = true;
                IsEditButtonEnable = false;
            }
            RaisePropertyChanged("ClassLevel");
            RaisePropertyChanged("Subject");
            RaisePropertyChanged("Topic");
            RaisePropertyChanged("TopicNo");
            RaisePropertyChanged("KIType");
            RaisePropertyChanged("Content");
        }

        public int Add(KnowledgeItem item)
        {
            return _kiAccessor.Add(item);
        }

        public bool Save(KnowledgeItem item)
        {
            return _kiAccessor.Update(item);
        }


        #endregion
    }
}
